﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MyLibrary.Net
{
    /// <summary>
    /// 数据块类
    /// </summary>
    public class DataBlock
    {
        byte[] _buffer;
        int _readIndex;
        int _writeIndex;

        /// <summary>
        /// 数据读取指针
        /// </summary>
        public int ReadIndex
        {
            get { return _readIndex; }
            set 
            {
                if (value < 0)
                    throw new ArgumentOutOfRangeException();
                if (_readIndex > _writeIndex)
                    throw new ArgumentOutOfRangeException("读指针不能超过写指针");
                _readIndex = value;
            }
        }

        /// <summary>
        /// 数据写指针
        /// </summary>
        public int WriteIndex
        {
            get { return _writeIndex; }
            set { _writeIndex = value; }
        }

        /// <summary>
        /// 数据块长度
        /// </summary>
        public int DataLength
        {
            get { return _writeIndex - _readIndex; }
        }

        /// <summary>
        /// 得到还可写入缓冲区长度
        /// </summary>
        public int WriteableLength
        {
            get { return _buffer.Length - _readIndex; }
        }

        /// <summary>
        /// 数据块内容
        /// </summary>
        public byte[] Buffer
        {
            get { return _buffer; }
            set { _buffer = value; }
        }

        /// <summary>
        /// 获得缓冲区长度
        /// </summary>
        public int BufferLength
        {
            get { return _buffer.Length; }
        }

        /// <summary>
        /// 有效数据的数组段
        /// </summary>
        public ArraySegment<byte> ArraySegment
        {
            get 
            {
                ArraySegment<byte> result = new ArraySegment<byte>(this._buffer, ReadIndex, DataLength);
                return result;
            }
            set 
            {
                _buffer = value.Array;
                ReadIndex = value.Offset;
                WriteIndex = value.Offset + value.Count;
            }
        }

        /// <summary>
        /// 获得缓冲区是否已满
        /// </summary>
        public bool IsFull
        {
            get { return WriteableLength == 0; }
        }

        public DataBlock() : this(1024)
        { }

        public DataBlock(byte[] data)
        {

        }

        public DataBlock(int size)
        {
            this._buffer = new byte[size];
        }

        public DataBlock(byte[] data, int startIndex, int length)
        {
            this._buffer = data;
            this._readIndex = startIndex;
            this._writeIndex = length;
        }

        public DataBlock(ArraySegment<byte> data)
        {
            this.ArraySegment = data;
        }

        /// <summary>
        /// 复制有效的数据到数组中
        /// </summary>
        /// <returns></returns>
        public byte[] ToArray()
        {
            byte[] result = new byte[DataLength];
            Array.Copy(_buffer, ReadIndex, result, 0, DataLength);
            return result;
        }

        /// <summary>
        /// 重设缓冲区大小
        /// </summary>
        /// <param name="newSize"></param>
        public void Resize(int newSize)
        {
            Array.Resize<byte>(ref _buffer, newSize);
            ReadIndex = 0;
            Reset();
        }

        /// <summary>
        /// 重置数据块状态
        /// </summary>
        public void Reset()
        {
            WriteIndex = ReadIndex = 0;
        }

        /// <summary>
        /// 向缓冲区写入一个Byte
        /// </summary>
        /// <param name="b">写入的Byte值</param>
        public void Add(byte b)
        {
            _buffer[WriteIndex] = b;
            WriteIndex++;
        }

        /// <summary>
        /// 向缓冲去写入一串数据
        /// </summary>
        /// <param name="array">要写入的数据串</param>
        /// <param name="offset">开始写入数据的偏移量</param>
        /// <param name="count">写入数据量</param>
        public void Add(byte[] array, int offset, int count)
        {
            for (int i = 0; i < count; i++)
                Add(array[i + offset]);
        }

        /// <summary>
        /// 合并两个数据块
        /// </summary>
        /// <param name="block1">数据块1</param>
        /// <param name="block2">数据块2</param>
        /// <returns>合并后的数据块</returns>
        public static DataBlock operator +(DataBlock block1, DataBlock block2)
        {
            if (block1 == null && block2 == null)
                return null;
            else if (block1 == null)
            {
                DataBlock result = new DataBlock(block2.DataLength);
                result.Add(block2._buffer, block2.ReadIndex, block2.DataLength);
                return result;
            }
            else if (block2 == null)
            {
                DataBlock result = new DataBlock(block1.DataLength);
                result.Add(block1._buffer, block1.ReadIndex, block1.DataLength);
                return result;
            }
            else
            {
                DataBlock result = new DataBlock(block1.DataLength + block2.DataLength);
                result.Add(block1._buffer, block1.ReadIndex, block1.DataLength);
                result.Add(block2._buffer, block2.ReadIndex, block2.DataLength);
                return result;
            }
        }
    }
}
